//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics.Contracts;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using OpenLS.Spreadsheet.UI.Internals;
using OpenLS.UI;

namespace OpenLS.Spreadsheet.UI
{
    ///<summary>
    /// WPF control used to display an entire workbook.
    ///</summary>
    public class WorkbookControl : Control
    {

        /// <summary>
        /// Is the control in read-only mode? If true, the user cannot edit the workbook.
        /// </summary>
        public bool IsReadOnly
        {
            get { return (bool)GetValue(IsReadOnlyProperty); }
            set { SetValue(IsReadOnlyProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsReadOnly.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsReadOnlyProperty =
            DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(WorkbookControl), new UIPropertyMetadata(false, OnReadOnlyChanged));

        private static void OnReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WorkbookControl control = (WorkbookControl) d;
            bool oldvalue = (bool) e.OldValue;
            bool newValue = (bool) e.NewValue;
            if (oldvalue == newValue)
                return;
            if (newValue)
            {
                control.PreviewMouseDoubleClick += new System.Windows.Input.MouseButtonEventHandler(control.ControlPreviewMouseDoubleClick);
                control.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(control.ControlPreviewKeyDown);
                control.PreviewDrop +=new DragEventHandler(control.control_PreviewDrop);
                control.PreviewMouseMove += control.control_PreviewMouseMove;
            }
            else
            {
                control.PreviewMouseDoubleClick -= new System.Windows.Input.MouseButtonEventHandler(control.ControlPreviewMouseDoubleClick);
                control.PreviewKeyDown -= new System.Windows.Input.KeyEventHandler(control.ControlPreviewKeyDown);
                control.PreviewDrop -= new DragEventHandler(control.control_PreviewDrop);
                control.PreviewMouseMove -= control.control_PreviewMouseMove;
            }
        }

        private void control_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            ScrollBar scrollBar = WindowServices.GetAncestor<ScrollBar>(e.OriginalSource);
            e.Handled = scrollBar == null;
        }

        private void control_PreviewDrop(object sender, DragEventArgs e)
        {
            e.Handled = true;
        }

        void ControlPreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            Contract.Requires(IsReadOnly);
            switch (e.Key)
            {
                case Key.Down:
                    case Key.PageUp:
                    case Key.PageDown:
                    case Key.Up:
                    case Key.Left:
                    case Key.Right:

                    break;
                case Key.C:
                    e.Handled = (Keyboard.Modifiers != ModifierKeys.Control);
                    break;
                default:
                    e.Handled = true;
                    break;
            }
            
        }

        void ControlPreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Contract.Requires(IsReadOnly);
            e.Handled = true;
        }


        static WorkbookControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WorkbookControl), new FrameworkPropertyMetadata(typeof(WorkbookControl)));
            CellEditedEvent = EditionElement.CellEditedEvent.AddOwner(typeof (WorkbookControl));
        }

        public WorkbookControl()
        {
            Workbook = SpreadsheetDocument.Create().Workbook;
            SetBinding(SpreadsheetElement.WorkbookProperty,
                       new Binding
                           {
                               RelativeSource = new RelativeSource(RelativeSourceMode.Self),
                               Path = new PropertyPath("Workbook")
                           });
        }

        /// <summary>
        /// Returns the cell at a given visual position, null if outside the cells area
        /// </summary>
        /// <param name="point">The position relative to the current control</param>
        /// <returns></returns>
        public Cell GetCellAt (Point point)
        {
            var element = InputHitTest(point);
            if (element == null)
                return null;
            var grid = WindowServices.GetAncestor<WorksheetGrid>(element);
            if (grid == null)
                return null;
            var point2 = this.TranslatePoint(point, grid);
            var address = grid.GetCellAddressAt(point2);
            return SpreadsheetElement.GetWorksheet(grid)[address];
        }

        ///<summary>
        /// Get or set the workbook to display.
        ///</summary>
        public Workbook Workbook
        {
            get { return (Workbook)GetValue(WorkbookProperty); }
            set { SetValue(WorkbookProperty, value);
                }
        }

        // Using a DependencyProperty as the backing store for Workbook.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WorkbookProperty =
            DependencyProperty.Register("Workbook", typeof(Workbook), typeof(WorkbookControl), new UIPropertyMetadata(null));


        /// <summary>
        /// 
        /// </summary>
        public static readonly RoutedEvent CellEditedEvent;


        public event EventHandler<CellRoutedEventArgs> CellEdited
        {
            add
            {
                this.AddHandler(CellEditedEvent, value);
            }
            remove { this.RemoveHandler(CellEditedEvent, value); }
        }


    }
}
